home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / sviluppo / svilupp2 / amphn192.lha / src / delfph.c < prev    next >
C/C++ Source or Header  |  1996-11-16  |  10KB  |  325 lines

  1.  
  2. #include <clib/exec_protos.h>
  3. #include <clib/dos_protos.h>
  4.  
  5. #include <libraries/delfina.h>
  6. #include <exec/interrupts.h>
  7. #include <stdio.h>
  8. #include <dos/dos.h>
  9.  
  10. #include "delfph.h"
  11.  
  12. /* (note: tabsize=4) */
  13.  
  14.  
  15. /* prototypes */
  16. BOOL InitDelfina(void);
  17. void CleanupDelfina(void);
  18. BOOL StartDelfina(int, int, int, int);
  19. void StopDelfina(void);
  20. int DelfPacket(void *,int,ULONG *);
  21. int GetClosestDelfRate(int , int *, int *);
  22.  
  23. /* seven FIR lowpass filters, 33 taps. */
  24. #define TAPS 33
  25.  
  26. int d_fir2[TAPS]={0x2cd0, 0x33c7, 0xffff9bdb, 0xffffbac7, 0xe45d,
  27.     0x3261, 0xfffe45b1, 0x540d, 0x2db6c, 0xfffe4d8d,
  28.     0xfffbd861, 0x49f49, 0x560c8, 0xfff4cf9e, 0xfff9bd9e,
  29.     0x27e542, 0x469469, 0x27e542, 0xfff9bd9e, 0xfff4cf9e,
  30.     0x560c8, 0x49f49, 0xfffbd861, 0xfffe4d8d, 0x2db6c,
  31.     0x540d, 0xfffe45b1, 0x3261, 0xe45d, 0xffffbac7,
  32.     0xffff9bdb, 0x33c7, 0x2cd0 };
  33.     
  34. int d_fir3[TAPS]={0x202d, 0x4d23, 0xfffffc7f, 0xffff5e4b, 0xffff92c1,
  35.     0xf6b1, 0x163a0, 0xffff1eef, 0xfffd112c, 0xffffcf4e,
  36.     0x4df15, 0x31e72, 0xfff93064, 0xfff5ed69, 0x840fc,
  37.     0x277b75, 0x373633, 0x277b75, 0x840fc, 0xfff5ed69,
  38.     0xfff93064, 0x31e72, 0x4df15, 0xffffcf4e, 0xfffd112c,
  39.     0xffff1eef, 0x163a0, 0xf6b1, 0xffff92c1, 0xffff5e4b,
  40.     0xfffffc7f, 0x4d23, 0x202d };
  41.     
  42. int d_fir4[TAPS]={0x2165, 0x33c9, 0xb8d, 0xffff90ce, 0xffff1551,
  43.     0xffff3f90, 0x7132, 0x21110, 0x28cd8, 0x8462,
  44.     0xfffc76e2, 0xfff96c09, 0xfffb7b5f, 0x4c37d, 0x1306a1,
  45.     0x201c6f, 0x256a61, 0x201c6f, 0x1306a1, 0x4c37d,
  46.     0xfffb7b5f, 0xfff96c09, 0xfffc76e2, 0x8462, 0x28cd8,
  47.     0x21110, 0x7132, 0xffff3f90, 0xffff1551, 0xffff90ce,
  48.     0xb8d, 0x33c9, 0x2165 };
  49.     
  50. int d_fir5[TAPS]={0xfffff453, 0xffffbfdf, 0xffff918d, 0xffff947d, 0xa7b,
  51.     0xe904, 0x1b2ac, 0x19835, 0x4dc, 0xfffd4c27,
  52.     0xfffaf62b, 0xfffb408d, 0xffffe705, 0x8d8b2, 0x13b901,
  53.     0x1cabd2, 0x20223e, 0x1cabd2, 0x13b901, 0x8d8b2,
  54.     0xffffe705, 0xfffb408d, 0xfffaf62b, 0xfffd4c27, 0x4dc,
  55.     0x19835, 0x1b2ac, 0xe904, 0xa7b, 0xffff947d,
  56.     0xffff918d, 0xffffbfdf, 0xfffff453 };
  57.     
  58. int d_fir6[TAPS]={0xffffdf1d, 0xffffc175, 0xffffbf0e, 0x4a8, 0x9a59,
  59.     0x13f81, 0x16de8, 0x9e44, 0xfffeb963, 0xfffc7301,
  60.     0xfffb3fe4, 0xfffcc54b, 0x1f380, 0xa4424, 0x139add,
  61.     0x1afa46, 0x1dc756, 0x1afa46, 0x139add, 0xa4424,
  62.     0x1f380, 0xfffcc54b, 0xfffb3fe4, 0xfffc7301, 0xfffeb963,
  63.     0x9e44, 0x16de8, 0x13f81, 0x9a59, 0x4a8,
  64.     0xffffbf0e, 0xffffc175, 0xffffdf1d };
  65.     
  66. int d_fir7[TAPS]={0xffffed47, 0x172a, 0x5a1d, 0xb53d, 0xf3ac,
  67.     0xcaff, 0x11b, 0xfffe9ecb, 0xfffd138e, 0xfffc2f17,
  68.     0xfffce3ea, 0xffffe201, 0x532d2, 0xc0786, 0x12dbab,
  69.     0x17e98c, 0x19c6e3, 0x17e98c, 0x12dbab, 0xc0786,
  70.     0x532d2, 0xffffe201, 0xfffce3ea, 0xfffc2f17, 0xfffd138e,
  71.     0xfffe9ecb, 0x11b, 0xcaff, 0xf3ac, 0xb53d,
  72.     0x5a1d, 0x172a, 0xffffed47 };
  73.     
  74. int d_fir8[TAPS]={0x2ab1, 0x5e23, 0x9a09, 0xb6de, 0x8687,
  75.     0xffffe6ea, 0xfffedd9e, 0xfffdacaf, 0xfffcd31c, 0xfffcf150,
  76.     0xfffe9517, 0x1fd6b, 0x6ed43, 0xca374, 0x1200e3,
  77.     0x15d523, 0x1738a9, 0x15d523, 0x1200e3, 0xca374,
  78.     0x6ed43, 0x1fd6b, 0xfffe9517, 0xfffcf150, 0xfffcd31c,
  79.     0xfffdacaf, 0xfffedd9e, 0xffffe6ea, 0x8687, 0xb6de,
  80.     0x9a09, 0x5e23, 0x2ab1 };
  81.         
  82. int *d_firs[7] = {d_fir2, d_fir3, d_fir4, d_fir5, d_fir6, d_fir7, d_fir8 };        
  83.  
  84. /* internal variables, don't worry about these.. :) */        
  85. struct Library *DelfinaBase;
  86. extern int delfcode;
  87. struct Interrupt delfint;
  88. struct DelfPrg *delfprg;
  89. int delfopen=0,delfbuf,delfrecbuf,delfcopyflags;
  90. int d_freqtab[28] = {8000, 9600, 8000, 16000, 9600, 8000, 9600, 27429, 27429,
  91.     8000, 27429, 9600, 16000, 27429, 48000, 32000, 27429, 8000, 27429, 9600,
  92.     32000, 48000, 27429, 16000, 48000, 27429, 32000, 48000 };
  93. int d_divtab[28] = {5, 5, 4, 7, 4, 3, 3, 8, 7, 2, 6, 2, 3, 5, 8, 5, 4, 1, 
  94.                     3, 1, 3, 4, 2, 1, 2, 1, 1, 1 };
  95.  
  96.  
  97. /* some more important variables: */
  98.  
  99. int delfsig  = 0;    /* signal _mask_ to wait, pass this directly to Wait() */
  100. int delfrate = 0;       /* the actual sample rate currently in use */
  101.  
  102.  
  103.  
  104. /*****************************************************************
  105.     Init Delfina stuff. 
  106.     
  107.     Opens delfina.library etc. Call this function only once, when
  108.     amiphone is started (or when user selects Delfina as sampler).
  109.     This function will also allocate 'delfsig' signal bit (See above)
  110.     
  111.     Result: TRUE if succeeded, FALSE if not
  112.     
  113.     Usually only fails if Delfina board is not installed.
  114. ******************************************************************/
  115. BOOL InitDelfina(void)
  116. {
  117.     if (delfopen) { /* just a check, if we are called multiple times */
  118.         delfopen++;
  119.          return(TRUE);    
  120.     }
  121.     
  122. /* open library */    
  123.     if (!(DelfinaBase=OpenLibrary("delfina.library",2))) return(FALSE);
  124.         
  125. /* add program */        
  126.     if (!(delfprg=Delf_AddPrg(&delfcode))) {
  127.         CloseLibrary(DelfinaBase); DelfinaBase = NULL;
  128.         return(FALSE);
  129.     }
  130.         
  131. /* create intserver, allocate sigbit */        
  132.     memset(&delfint,0,sizeof(struct Interrupt));
  133.     if (!Delf_AddIntServer(delfprg->prog,&delfint)) {
  134.         Delf_RemPrg(delfprg);delfprg=NULL;
  135.         CloseLibrary(DelfinaBase); DelfinaBase = NULL;
  136.         return(FALSE);
  137.     }
  138.     delfsig=(int)delfint.is_Data;    
  139.     
  140.     delfopen++;
  141.     return(TRUE);
  142. }
  143.  
  144.     
  145.     
  146.     
  147. /*****************************************************************
  148.     Cleanup Delfina stuff    
  149.     
  150.     Deallocates everything that was allocated in InitDelfina().
  151.     Call this in exit of amiphone, or when user deselects Delfina
  152.     as sampler.. 
  153. ******************************************************************/
  154. void CleanupDelfina(void)
  155. {
  156.     if (--delfopen) return;
  157.     
  158.     Delf_RemIntServer(delfprg->prog);
  159.     Delf_RemPrg(delfprg);
  160.     CloseLibrary(DelfinaBase);
  161. }
  162.  
  163.  
  164.  
  165.  
  166. /*****************************************************************
  167.     Start recording.
  168.     
  169.     Inputs:
  170.         samplerate    = sample rate in Hz. The closest available
  171.                       freq will be returned in delfrate
  172.                       
  173.         bufsize        = packet size in SAMPLES. Must be a multiple               
  174.                       of 8!
  175.                       
  176.         compr        = compression mode. 0=none (8bit signed),              
  177.                       1=adpcm2, 2=adpcm3
  178.                       
  179.         ch            = input channel, 0=left, 1=right
  180.         
  181.     Result: TRUE if succeeded, FALSE if not    
  182. ******************************************************************/
  183.  
  184. BOOL StartDelfina(int samplerate, int bufsize, int compr, int ch)
  185. {
  186.     int freq,div;
  187.     
  188. /* find the closest frequency, and freq and div values. */
  189.     delfrate = GetClosestDelfRate(samplerate, &freq, &div);
  190.     
  191. /* allocate delfina's data buffer */    
  192.     if (compr) 
  193.         delfbuf=Delf_AllocMem(bufsize/4,DMEMF_YDATA|DMEMF_ALIGN_8K);
  194.     else
  195.         delfbuf=Delf_AllocMem(bufsize,DMEMF_YDATA|DMEMF_ALIGN_8K);
  196.         
  197.     if (!delfbuf) 
  198.     {
  199.         printf("Delf_AllocMem 1 failed!\n");
  200.         return(FALSE);
  201.     }
  202.  
  203. /* allocate delfina's rec buffer */
  204.     delfrecbuf=Delf_AllocMem(bufsize*2*div,DMEMF_LDATA);
  205.     if (!delfrecbuf) {
  206.         Delf_FreeMem(delfbuf,DMEMF_YDATA);
  207.         printf("Delf_AllocMem 2 failed!\n");
  208.         return(FALSE);
  209.     }
  210.     
  211. /* tell parameters to DSP code */        
  212.     Delf_Run(delfprg->prog,0,0,delfbuf,bufsize,compr,div-1);
  213.     
  214. /* setup fir filter */    
  215.     if (div>1)
  216.         Delf_CopyMem((ULONG)d_firs[div-2],delfprg->ldata,TAPS*4,DCPF_XDATA|DCPF_32BIT|DCPF_TO_DELFINA);
  217.         
  218. /* allocate audio, start recording */
  219.     if (!Delf_AllocAudio(delfrecbuf,delfrecbuf,bufsize*2*div,delfprg->prog+2+(ch ? 0:2))) {
  220.         Delf_FreeMem(delfrecbuf,DMEMF_LDATA);
  221.         Delf_FreeMem(delfbuf,DMEMF_YDATA);
  222.         printf("Delf_AllocAudio Failed!\n");
  223.         return(FALSE);
  224.     }
  225.     
  226. /* set frequency */    
  227.     {
  228.         struct TagItem tagitems[2];
  229.         tagitems[0].ti_Tag = DA_Freq;  tagitems[0].ti_Data = freq;
  230.         tagitems[1].ti_Tag = TAG_DONE; tagitems[1].ti_Data = NULL;
  231.         Delf_SetAttrsA(tagitems);
  232.     }
  233.     
  234. /* setup copy flags for DelfPacket */    
  235.     if (compr==2) delfcopyflags=DCPF_YDATA|DCPF_TO_AMY|DCPF_24BIT;
  236.     else          delfcopyflags=DCPF_YDATA|DCPF_TO_AMY|DCPF_16BIT;
  237.     
  238.     return(TRUE);
  239. }
  240.  
  241.  
  242.  
  243. /* This function pulled out of StartDelfina().  Returns the "virtual" sampling
  244.    rate that is closest to the desired rate (ulIdealRate).  If non-NULL,
  245.    *pnOptSetFreq is set to the actual sampling rate that would be used,
  246.    and *pnOptSetDiv is set to the division rate (every n'th byte kept, wheere
  247.    n==*pnOptSetDiv). */
  248. int GetClosestDelfRate(int nIdealRate, int * pnOptSetFreq, int * pnOptSetDiv)
  249. {    
  250.     int x, min=10000;
  251.     int freq, div;
  252.     
  253.     for (x=0;x<28;x++) {
  254.         if (abs(nIdealRate-d_freqtab[x]/d_divtab[x])<min) {
  255.             freq = d_freqtab[x];
  256.             div  = d_divtab[x];
  257.             min=abs(nIdealRate-freq/div);
  258.         }
  259.     }
  260.     if (pnOptSetFreq) *pnOptSetFreq = freq;
  261.     if (pnOptSetDiv)  *pnOptSetDiv  = div;
  262.     return(freq/div);
  263. }
  264.  
  265.  
  266.  
  267.  
  268.  
  269. /*****************************************************************
  270.     Stop recording
  271.     
  272.     Deallocates everything that StartDelfina() allocated.
  273. ******************************************************************/
  274. void StopDelfina(void)
  275. {
  276.     Delf_FreeAudio();
  277.     Delf_FreeMem(delfrecbuf,DMEMF_LDATA);
  278.     Delf_FreeMem(delfbuf,DMEMF_YDATA);
  279. }
  280.  
  281.  
  282.  
  283. /*****************************************************************
  284.     Copy packet data from delfina
  285.  
  286.     Use this function to get the packet data. New packet data is 
  287.     available when you receive the 'delfsig' signal, so your main
  288.     loop may be something like this:
  289.     
  290.     
  291.     for (;;) {
  292.         Wait(delfsig);
  293.         DelfPacket(tempbuf);
  294.         Transmit(tempbuf);
  295.     }
  296.     
  297.     Input:
  298.         buf  = pointer to buffer where the packet will be copied.
  299.         size = packet size in bytes
  300.         setJoinCode = pointer to a ULONG that will be filled in
  301.                   with the current ADPCM JoinCode.
  302.                   
  303.     Result:    
  304.         sum of all samples. If you want to know the average volume,
  305.         divide this by the number of samples in the packet.. 
  306.         
  307.     Note: since this function really just calls Delf_CopyMem, you    
  308.     may want to implement this as macro instead.. 
  309.     
  310.     
  311. ******************************************************************/
  312. int DelfPacket(void *buf, int size, ULONG * setJoinCode)
  313. {
  314.     int estmax,delta,vol,currbuf;
  315.  
  316.     currbuf=Delf_Peek(delfprg->xdata+3,DMEMF_XDATA);
  317.     Delf_CopyMem(currbuf,(ULONG)buf,size,delfcopyflags);
  318.     
  319.     vol=Delf_Peek(delfprg->xdata,DMEMF_XDATA);
  320.     estmax=Delf_Peek(delfprg->xdata+1,DMEMF_XDATA);
  321.     delta=Delf_Peek(delfprg->xdata+2,DMEMF_XDATA);
  322.     *setJoinCode = (delta<<16) | (estmax & 0xffff);
  323.     
  324.     return(vol);
  325. }